﻿using UnityEngine;

namespace Vosvek.ProjectRogue
{

    [RequireComponent(typeof(Collider2D),
                      typeof(SpriteRenderer))]
    public class Door : MonoBehaviour, IPlayerUsable
    {
        [SerializeField] Sprite closedSprite;
        [SerializeField] Sprite openSprite;
        [SerializeField] LockBolt lockBolt;
        [SerializeField] Trap trap;
        [SerializeField] bool isOpen;

        SpriteRenderer spriteRenderer;
        new Collider2D collider;

        public LockBolt LockBolt { get { return lockBolt; } }
        public Trap Trap { get { return trap; } }
        public bool IsOpen { get { return isOpen; } }

        void Start()
        {
            spriteRenderer = GetComponent<SpriteRenderer>();
            collider = GetComponent<Collider2D>();
        }

        public void Unlock(Actor user)
        {
            lockBolt.Unlock(user);
        }

        public void Untrap(Actor user)
        {
            trap.Untrap(user);
        }

        public void Open(Actor user)
        {
            // EALY EXIT: Door is already open.
            if (isOpen) return;

            // If the trap is enabled, apply effects to the user.
            if (!trap.IsDisabled)
            {
                // TODO: Door::ApplySpellEffect for user / trap.
                //user.ApplySpellEffect(trap.SpellEffect);
            }

            // If the door is locked, try to unlock it.
            if (lockBolt.IsLocked)
            {
                Unlock(user);
            }
            // Otherwise, open the door, and update the sprite and collider.
            else
            {
                isOpen = true;
                UpdateCollider();
                UpdateSprite();
            }
        }

        public void Close(Actor user)
        {
            // EARLY EXIT: Do nothing if the door is already closed.
            if (!isOpen) return;

            isOpen = false;
            UpdateCollider();
            UpdateSprite();
        }

        public void OnPlayerUse(Player player)
        {
            // Switch: If the door is open, close it. If the door is closed, 
            // try to open it.
            if (isOpen)
            {
                Close(player);
            }
            else
            {
                Open(player);
            }
        }

        void UpdateSprite()
        {
            // If there is a sprite renderer, set the sprite to the open or
            // closed sprite based on whether the door is open.
            if (spriteRenderer != null)
            {
                if (isOpen && openSprite != null)
                {
                    spriteRenderer.sprite = openSprite;
                }
                else if (closedSprite != null)
                {
                    spriteRenderer.sprite = closedSprite;
                }
            }
        }

        void UpdateCollider()
        {
            // If there is a collider, enabled or disable based on whether the 
            // door is open.
            if (collider != null)
            {
                if (isOpen)
                {
                    collider.enabled = false;
                }
                else
                {
                    collider.enabled = true;
                }
            }
        }

        void OnValidate()
        {
            // If there is no sprite renderer, try to get it.
            if (spriteRenderer == null)
            {
                spriteRenderer = GetComponent<SpriteRenderer>();
            }

            // UpdateSprite. Note, skips if there is no sprite renderer.
            UpdateSprite();

            // If there is no collider, try to get it.
            if (collider == null)
            {
                collider = GetComponent<Collider2D>();
            }

            // Ensure the collider is enabled only when the door is closed.
            UpdateCollider();
        }
    }

}
